/**
 * 使用方法:
 * let lazy = new LazyLoad(window);
 * // 当页面lazyload图片dom新增时调用update方法刷新lazy数据
 * lazy.update();
 */

 ((global, factory) => {
    typeof module !== 'undefined' && typeof module.exports === 'object' ?
        module.exports = factory() : (global.LazyLoad = factory());
 })(window, function () {
    // 自定义标签名
    const CUSTOM_ELEMENT_NAME = 'lazy-image';
    const ANIMATION_CLASS = 'lazy-image-load';
    // 样式常量
    const DISPLAY_DEFAULT = 'inline-block';
    const DISPLAY_INLINE = 'inline';
    const POSITION_DEFAULT = 'relative';
    const POSITION_STATIC = 'static';

    const IMAGE_CLASS = 'lazy-image-real-dom';
    const INITIAL_IMAGE = 'http://qn.zhangyy.xyz/5c9206d469.jpeg';
    // 自定义类
    class LazyImage extends HTMLElement {
        constructor() {
            super();
        }
        // 初始化元素
        init() {
            if (!LazyImage.$id) {
                LazyImage.$id = 0;
            }
            LazyImage.$id += 1;
            this.$id = LazyImage.$id;

            // 是否已经加载图片
            this.loaded = false;

            let styleSheets = window.getComputedStyle(this, null);
            let display = styleSheets.display;
            let position = styleSheets.position;
            this.setStyle(this, {
                display: display === DISPLAY_INLINE ? DISPLAY_DEFAULT : display,
                position: position === POSITION_STATIC ? POSITION_DEFAULT : position,
            });
            this.activeClass = this.getAttribute('active-class') || ANIMATION_CLASS;
            this.initSrc = this.getAttribute('init-src') || INITIAL_IMAGE;
            // 插入图片dom
            this.img = this.insertImage();
            // 注册过的自定义组件在dom更新时会重新注册，但是插入的dmo不会被注销，所以只更换自定义dom的外壳，
            // 插入的dom状态保持原样
            if (this.loaded) {
                this.loadEnd();
            }
            this.setStyle(this.img, {
                position: 'absolute',
                left: '0',
                top: '0',
                width: '100%',
                height: '100%',
            });
        }
        // 插入图片dom
        insertImage() {
            let oImg = this.querySelector(`.${IMAGE_CLASS}`);
            if (!oImg) {
                oImg = document.createElement('img');
                oImg.src = this.initSrc;
                oImg.className = IMAGE_CLASS;
                this.insertBefore(oImg, this.firstChild);
            } else if (this.getAttribute('src') === oImg.src) {
                this.loaded = true;
            }
            return oImg;
        }
        
        // 给dom设置样式
        setStyle(dom, styles) {
            Object.keys(styles).forEach((prop) => {
                dom.style[prop] = styles[prop];
            });
        }
        // 加载图片
        load() {
            if (this.loaded) {
                return;
            }
            this.img.src = this.getAttribute('src');
            this.img.className += ` ${this.activeClass}`;
            this.loaded = true;
            this.addEventListener('webkitAnimationEnd', this.loadEnd, false)
        }
        loadEnd(e) {
            this.img.className = this.img.className.replace(this.activeClass, '');
            this.removeEventListener('webkitAnimationEnd', this.loadEnd);
        }
        // dom首次被插入文档DOM时调用
        connectedCallback() {
            this.init();
        }
        // dom移除时调用
        disconnectedCallback() {
            this.loadEnd();
        }
    }
    // 注册自定义组件
    customElements.define(CUSTOM_ELEMENT_NAME, LazyImage);

    class LazyLoad {
        constructor(container = window) {
            // wrap为滑动容器的对象
            // container为dom容器，做查询dom的容器
            this.wrap = container;
            if (container === window) {
                container = document;
            }
            this.container = container;
            this.lazyImages = [];
            this.init();
        }
        init() {
            this.insertStyle();
            this.update();
            this.registerScroll();
        }
        // 插入样式
        insertStyle() {
            let oStyle = document.createElement('style');
            oStyle.innerHTML = `
                .${ANIMATION_CLASS} {
                    animation: lazyImageLoad 1s;
                }
                @keyframes lazyImageLoad {
                    from {
                        opacity: 0;
                    }
                    to {
                        opacity: 1;
                    }
                }
             `;
             document.head.appendChild(oStyle);
        }
        // 类数组转换
        makeArray(arrayLike) {
            return Array.prototype.slice.call(arrayLike);
        }
        // 更新需要懒加载的dom
        update() {
            setTimeout(() => {
                this.lazyImages = this.makeArray(this.container.querySelectorAll('lazy-image'))
                    .filter((oItem) => {
                        return !oItem.loaded;
                    });
                this.loadImage();
            }, 0);
        }
        // 加载更多图片
        loadImage() {
            this.lazyImages = this.lazyImages.filter((oItem) => {
                let rect = oItem.getBoundingClientRect();
                let top = rect.top;
                if (top < window.innerHeight) {
                    oItem.load();
                    return false;
                }
                return true;
            });
        }
        // 注册scroll事件
        registerScroll() {
            this.wrap.addEventListener('scroll', (e) => {
                if (this.lazyImages.length) {
                    this.loadImage();
                }
            });
        }
    }
    return LazyLoad;
 });